原理
背景
Canvas在drawText的时候,如果需要每次都计算字体的大小,边距之类的话,就会非常耗时,导致drawText时间会拉的很长,为了提高效率,android4.0之后引入了TextLayoutCache,使用了LRU缓存了字型,边距等数据,提升了drawText的速度,在4.4中,这个cache的大小是0.5m,全局使用,并且受到系统的控制会在Activity的configurationChanged, onResume, lowMemory, updateVisibility等时机,会调用Canvas.freeTextLayoutCache来释放这部分内存
1 | // /frameworks/minikin/libs/minikin/Layout.cpp中的LayoutCache |
setText
从以下源码可知,假如textView的宽高是wrap_content的话,会重新触发requestLayout方法,从measure开始重新来一遍否则从layout开始重新来一遍,所以是非常耗时的一个过程.
1 | private void setText(CharSequence text, BufferType type, |
优化方向
- 我们可以在View这一层根据文字内容,文字大小等信息封装一个可复用的TextLayoutBuilder这样就不需要重新Layout相同的内容
- 根据4.0之后增加的LruCache原理,在子线程层创建一个warmUpHandler用于预热所要draw的Text,这样在ui线程真正要画它的时候,可以直接从cache中拿,起到加速的效果
TextLayoutBuilder
根据上面的两个优化点,所以有了facebook开源的TextLayoutBuilder项目
框架图

部分源码
如何build一个Layout
1 | /** |
如何确定复用的规则
1 | //cache的key值 |
疑惑解答
staticLayout不支持maxLine的构造函数
faceBook的做法
1 | //编译替换?TODO |
反射构造函数
1 | public class StaticLayoutWithMaxLines { |
LinkageError的异常原因
//TODO 20171029
实际运用
Layout复用管理
1 | import android.graphics.Canvas; |
如何封装view
1 | import android.graphics.Canvas; |
TODO
LinkageError的异常原因